; frame.asm
; screen handling

	.include "global.inc"
	.include "colors.inc"
	
	_IN_FRAME = 1
	.include "frame.inc"

	SPACE = 0
	BLOCK = 1
	PRELF = 2
	
	FIRST_1x1 = 3
	FIRST_2x2 = FIRST_1x1 + MAX_OBJECTS_1x1
	FIRST_NUM = FIRST_2x2 + 4*MAX_OBJECTS_2x2
	
	.macro CLR video_base, color_base
			.local l1
			ldx #0
	l1:		lda bkvid, x
			sta video_base, x
			lda bkvid+$0100, x
			sta video_base+$0100, x
			lda bkclr, x
			sta color_base, x
			lda bkclr+$0100, x
			sta color_base+$0100, x
			inx
			bne l1
	.endmacro	
	
	.segment "BSS"
	
active2x2:	.res MAX_OBJECTS_2x2 * 3
poslo2x2:	.res MAX_OBJECTS_2x2 * 3
poshi2x2:	.res MAX_OBJECTS_2x2 * 3
color2x2:	.res MAX_OBJECTS_2x2
datalo2x2:	.res MAX_OBJECTS_2x2
datahi2x2:	.res MAX_OBJECTS_2x2
coll2x2:	.res MAX_OBJECTS_2x2

active1x1:	.res MAX_OBJECTS_1x1 * 3
poslo1x1:	.res MAX_OBJECTS_1x1 * 3
poshi1x1:	.res MAX_OBJECTS_1x1 * 3
color1x1:	.res MAX_OBJECTS_1x1
datalo1x1:	.res MAX_OBJECTS_1x1
datahi1x1:	.res MAX_OBJECTS_1x1
coll1x1:	.res MAX_OBJECTS_1x1

char1:		.res 1 ; = tmpptr3
char2:		.res 1 ; = tmpptr3+1
savex = tmpptr4

	.segment "CODE"
	
initfrm:	; clear screen & char ram
			ldx #0
			txa
@clr:		sta CHAR_BASE0, x 
			sta CHAR_BASE0+$0100, x 
			sta CHAR_BASE0+$0200, x 
			sta CHAR_BASE0+$0300, x 
			sta CHAR_BASE1, x 
			sta CHAR_BASE1+$0100, x 
			sta CHAR_BASE1+$0200, x 
			sta CHAR_BASE1+$0300, x 
			inx
			bne @clr
			; init fixed chars
			ldx #8
			lda #$FF
@chset1:	sta CHAR_BASE0+8*BLOCK, x
			sta CHAR_BASE1+8*BLOCK, x
			dex
			bpl @chset1
			ldx #6
			lda #$FE
@chset2:	sta CHAR_BASE0+8*PRELF+1, x
			sta CHAR_BASE1+8*PRELF+1, x
			dex
			bpl @chset2
			; life indicators
			ldx #11*8-1
@chset3:	lda plrlife, x
			sta CHAR_BASE0+8*FIRST_NUM, x
			sta CHAR_BASE1+8*FIRST_NUM, x
			dex
			bpl @chset3
			; init objects
			lda #0
			ldx #MAX_OBJECTS_2x2*3-1
@io2_1:		sta active2x2, x
			dex
			bpl @io2_1
			ldx #MAX_OBJECTS_2x2-1
@io2_2:		sta coll2x2, x
			dex
			bpl @io2_2
			ldx #MAX_OBJECTS_1x1*3-1
@io1_1:		sta active1x1, x
			dex
			bpl @io1_1		
			ldx #MAX_OBJECTS_1x1-1
@io1_2:		sta coll1x1, x
			dex
			bpl @io1_2		
			; init frames
			lda VIC_BASE+2
			and #$7F
			sta vicreg2
			ora #$80
			sta vicreg2+1
			; clr screen
			CLR VIDEO_BASE0, COLOR_BASE0
			CLR VIDEO_BASE1, COLOR_BASE1
			rts

nextfrm:	; switch frame
			ldx curfrm
			lda vicreg2, x
			sta VIC_BASE+2
			lda vicreg5, x
			sta VIC_BASE+5
			txa
			eor #1
			sta curfrm
			rts

docoll:		; handle collisions, char1 .. char of spr1, char2 .. char of spr2
;	FIRST_1x1 = 2
;	FIRST_2x2 = FIRST_1x1 + MAX_OBJECTS_1x1
			stx savex
			lda char1
			cmp #FIRST_1x1
			bcc @chk2
			cmp #FIRST_2x2
			bcc @spr1x1_1
;			sec
			sbc #FIRST_2x2
			lsr
			lsr
			tax
			inc coll2x2, x
			bne @chk2
@spr1x1_1:	sec
			sbc #FIRST_1x1
			tax
			inc coll1x1, x
@chk2:		lda char2
			cmp #FIRST_1x1
			bcc @done
			cmp #FIRST_2x2
			bcc @spr1x1_2
;			sec
			sbc #FIRST_2x2
			lsr
			lsr
			tax
			inc coll2x2, x
			bne @done
@spr1x1_2:	sec
			sbc #FIRST_1x1
			tax
			inc coll1x1, x
@done:		ldx savex
			rts

; collision check & pixel combination
;			tmpptr1 ... bk char
;			tmpptr2 ... new char 
;			A,Y .. scratch.
chmerge:	ldy #7
@chklp:		lda (tmpptr1), y
			and (tmpptr2), y
			beq @nocoll
			jsr docoll			; collision detected
			ldy #0			
@nocoll:	dey
			bpl @chklp
			ldy #7
@mrglp:		lda (tmpptr1), y
			ora (tmpptr2), y
			sta (tmpptr2), y
			dey
			bpl @mrglp
			rts

clccbase:	shl16 tmpptr1, 3
			shl16 tmpptr2, 3
			rts
			
	.macro handle_collision char_base ; A .. bk char, y .. new char
			sta char1
			sty char2
			sta tmpptr1
			sty tmpptr2
			lda #0
			sta tmpptr1+1
			sta tmpptr2+1
			jsr clccbase
			clc
			lda tmpptr1+1
			adc #>char_base
			sta tmpptr1+1
			clc
			lda tmpptr2+1
			adc #>char_base
			sta tmpptr2+1
			jsr chmerge
			lda char1
			ldy char2
	.endmacro 

	.macro copy_object_2x2 char_base, index
		.local src, tgt
			lda datalo2x2 + index
			sta src+1
			lda datahi2x2 + index
			sta src+2
			ld16 tgt+1, char_base+8*FIRST_2x2 + index*32
			ldx #31
	src:	lda $FFFF, x
	tgt:	sta $FFFF, x
			dex
			bpl src		
	.endmacro
	
	.macro show_object_2x2 base, index, frame, char_base
		.local tgt1, tgt2, loop, chk1, chk2, skp1, skp2
			clc
			lda poslo2x2+index
			sta poslo2x2+index+MAX_OBJECTS_2x2*(frame+1)
			sta tgt1+1
			lda poshi2x2+index
			sta poshi2x2+index+MAX_OBJECTS_2x2*(frame+1)
			adc #>base
			sta tgt1+2
			clc
			lda tgt1+1
			sta chk1+1
			adc #COLS
			sta tgt2+1
			sta chk2+1
			lda tgt1+2
			sta chk1+2
			adc #0
			sta tgt2+2
			sta chk2+2
			ldx #1
			ldy #FIRST_2x2+index*4+4
	loop:	dey
	chk2:	lda $FFFF, x
			beq skp2
			; collision check & pixel combination: A .. coll. char,  Y .. new char, index ... sprite index
			handle_collision char_base
	skp2:	tya
	tgt2:	sta $FFFF, x
			dey
	chk1:	lda $FFFF, x	
			beq skp1
			; collision check & pixel combination: A .. coll. char,  Y .. new char, index ... sprite index			
			handle_collision char_base  
	skp1:	tya
	tgt1:	sta $FFFF, x
			dex
			bpl loop
	.endmacro

	.macro color_object_2x2 base, index
		.local tgt1, tgt2
			lda poslo2x2+index
			sta tgt1+1
			clc
			lda poshi2x2+index
			adc #>base
			sta tgt1+2
			clc
			lda tgt1+1
			adc #COLS
			sta tgt2+1
			lda tgt1+2
			adc #0
			sta tgt2+2
			ldx #1
			lda color2x2+index
	tgt1:	sta $FFFF, x
	tgt2:	sta $FFFF, x
			dex
			bpl tgt1
	.endmacro

	.macro copy_object_1x1 char_base, index
		.local src, tgt
			lda datalo1x1 + index
			sta src+1
			lda datahi1x1 + index
			sta src+2
			ld16 tgt+1, char_base + 8*(FIRST_1x1 + index)
			ldx #7
	src:	lda $FFFF, x
	tgt:	sta $FFFF, x
			dex
			bpl src		
	.endmacro

	.macro show_object_1x1 base, index, frame, char_base
		.local @skip
			clc
			lda poslo1x1+index
			sta poslo1x1+index+MAX_OBJECTS_1x1*(frame+1)
			sta tmpptr3
			lda poshi1x1+index
			sta poshi1x1+index+MAX_OBJECTS_1x1*(frame+1)
			adc #>base
			sta tmpptr3+1
			ldy #0
			lda (tmpptr3), y
			beq @skip
			; collision check & pixel combination: A .. coll. char, Y .. new char, {1} ... sprite index
			ldy #FIRST_1x1+index
			handle_collision char_base
			ldy #0
@skip:		lda #FIRST_1x1+index			
			sta (tmpptr3), y
	.endmacro

	.macro color_object_1x1 base, index
		.local tgt
			clc
			lda poslo1x1+index
			sta tgt+1
			lda poshi1x1+index
			adc #>base
			sta tgt+2
			lda color1x1+index
	tgt:	sta $FFFF
	.endmacro
	
	.macro clr_object_2x2 base, index, bk
		.local tgt1, tgt2
			clc						; tgt
			lda poslo2x2+index
			sta tmpptr2
			lda poshi2x2+index
			adc #>base
			sta tmpptr2+1
			clc						; src
			lda poslo2x2+index
			adc #<bk
			sta tmpptr1
			lda poshi2x2+index
			adc #>bk
			sta tmpptr1+1
			ldy #0
			lda (tmpptr1), y
			sta (tmpptr2), y
			iny
			lda (tmpptr1), y
			sta (tmpptr2), y
			tya
			clc
			adc #COLS-1
			tay
			lda (tmpptr1), y
			sta (tmpptr2), y
			iny
			lda (tmpptr1), y
			sta (tmpptr2), y
	.endmacro

	.macro clr_object_1x1 base, index, bk
		.local tgt, src
			clc						; tgt
			lda poslo1x1+index
			sta tgt+1
			lda poshi1x1+index
			adc #>base
			sta tgt+2
			clc						; src
			lda poslo1x1+index
			adc #<bk
			sta src+1
			lda poshi1x1+index
			adc #>bk
			sta src+2
	src:	lda $FFFF
	tgt:	sta $FFFF
	.endmacro

	.macro draw_frame char_base, video_base, color_base, frame
		; clear background 
		.repeat MAX_OBJECTS_2x2, I
			lda active2x2+I+MAX_OBJECTS_2x2*(frame+1)
			bne :+
			jmp :++	
		:	clr_object_2x2 video_base, I+MAX_OBJECTS_2x2*(frame+1), bkvid
			clr_object_2x2 color_base, I+MAX_OBJECTS_2x2*(frame+1), bkclr
		:
		.endrep
		.repeat MAX_OBJECTS_1x1, I
			lda active1x1+I+MAX_OBJECTS_1x1*(frame+1)
			bne :+
			jmp :++	
		:	clr_object_1x1 video_base, I+MAX_OBJECTS_1x1*(frame+1), bkvid
			clr_object_1x1 color_base, I+MAX_OBJECTS_1x1*(frame+1), bkclr
		:
		.endrep
			; moving objects
		.repeat MAX_OBJECTS_2x2, I
			ldy #0
			lda active2x2+I
			sta active2x2+I+MAX_OBJECTS_2x2*(frame+1)
			bne :+
			jmp :++	
		:	lda #0
			sta coll2x2 + I
			copy_object_2x2 char_base, I
			show_object_2x2 video_base, I, frame, char_base
			color_object_2x2 color_base, I
		:
		.endrep
		.repeat MAX_OBJECTS_1x1, I
			lda active1x1+I
			sta active1x1+I+MAX_OBJECTS_1x1*(frame+1)
			bne :+
			jmp :++	
		:	lda #0
			sta coll1x1 + I
			copy_object_1x1 char_base, I
			show_object_1x1 video_base, I, frame, char_base
			color_object_1x1 color_base, I
		:
		.endrep
	.endmacro

drawfrm:	lda curfrm
			beq frm0
			jmp frm1
frm0:		draw_frame CHAR_BASE0, VIDEO_BASE0, COLOR_BASE0, 0
			rts
frm1:		draw_frame CHAR_BASE1, VIDEO_BASE1, COLOR_BASE1, 1
			rts			

showlife:	; x ... index, y ... lifes, A ... color
			sta char1	; save color
			sty char2	; save lifes
			; calc ptrs
			clc
			lda lifeposlo, x
			adc #<bkvid 
			sta tmpptr1
			lda lifeposhi, x
			adc #>bkvid
			sta tmpptr1+1
			clc
			lda lifeposlo, x
			adc #<bkclr 
			sta tmpptr2
			lda lifeposhi, x
			adc #>bkclr
			sta tmpptr2+1
			; set bk image
			ldy #0
			lda #PRELF
			sta (tmpptr1), y
			lda #BLACK
			sta (tmpptr2), y
			iny
			clc
			lda char2
			adc #FIRST_NUM
			sta (tmpptr1), y
			lda char1
			sta (tmpptr2), y
			; copy last row to frame buffers
			ldy #COLS-1 
@cploop:	lda bkvid+BOTTOM_ROW, y
			sta VIDEO_BASE0+BOTTOM_ROW, y
			sta VIDEO_BASE1+BOTTOM_ROW, y
			lda bkclr+BOTTOM_ROW, y
			sta COLOR_BASE0+BOTTOM_ROW, y
			sta COLOR_BASE1+BOTTOM_ROW, y
			dey
			bpl @cploop
			rts

clrlfbar:	; clear bottom life bar
			ldy #COLS-1 
@cploop:	lda #BLOCK
			sta bkvid+BOTTOM_ROW, y
			sta VIDEO_BASE0+BOTTOM_ROW, y
			sta VIDEO_BASE1+BOTTOM_ROW, y
			lda #BLACK
			sta bkclr+BOTTOM_ROW, y
			sta COLOR_BASE0+BOTTOM_ROW, y
			sta COLOR_BASE1+BOTTOM_ROW, y
			dey
			bpl @cploop
			rts

	.segment "RODATA" 

	BOTTOM_ROW = (ROWS-1)*COLS

lifeposlo:	.byte <(BOTTOM_ROW + 1),  <(BOTTOM_ROW + 3),  <(BOTTOM_ROW + 5)
			.byte <(BOTTOM_ROW + 8),  <(BOTTOM_ROW + 10), <(BOTTOM_ROW + 12)
			.byte <(BOTTOM_ROW + 15), <(BOTTOM_ROW + 17), <(BOTTOM_ROW + 19)   
lifeposhi:	.byte >(BOTTOM_ROW + 1),  >(BOTTOM_ROW + 3),  >(BOTTOM_ROW + 5)
			.byte >(BOTTOM_ROW + 8),  >(BOTTOM_ROW + 10), >(BOTTOM_ROW + 12)
			.byte >(BOTTOM_ROW + 15), >(BOTTOM_ROW + 17), >(BOTTOM_ROW + 19)   

	.segment "DATA"
	
curfrm:		.byte 0

vicreg2:	.byte 0, 0
vicreg5:	.byte $CD, $CE 

bkvid:		.repeat COLS
				.byte BLOCK
			.endrep 
			.repeat ROWS-2
				.byte BLOCK
				.repeat COLS-2
					.byte SPACE
				.endrep
				.byte BLOCK
			.endrep
			.repeat COLS
				.byte BLOCK
			.endrep 
			
bkclr:		.repeat COLS
				.byte BLACK
			.endrep 
			.repeat ROWS-2
				.byte BLACK
				.repeat COLS-2
					.byte WHITE
				.endrep
				.byte BLACK
			.endrep
			.repeat COLS
				.byte BLACK
			.endrep 

plrlife:	.byte $FF, $00, $44, $EA, $4A, $4A, $A4, $00 ; 0
			.byte $FF, $00, $44, $EC, $44, $44, $A4, $00 ; 1
			.byte $FF, $00, $44, $EA, $42, $44, $AE, $00 ; 2
			.byte $FF, $00, $4C, $E2, $44, $42, $AC, $00 ; 3
			.byte $FF, $00, $48, $E8, $4E, $44, $A4, $00 ; 4
			.byte $FF, $00, $4E, $E8, $4C, $42, $AC, $00 ; 5
			.byte $FF, $00, $46, $E8, $4C, $4A, $A4, $00 ; 6
			.byte $FF, $00, $4E, $E2, $44, $48, $A8, $00 ; 7
			.byte $FF, $00, $44, $EA, $44, $4A, $A4, $00 ; 8
			.byte $FF, $00, $44, $EA, $46, $42, $AC, $00 ; 9
			.byte $FF, $00, $40, $E0, $4E, $40, $A0, $00 ; -
